package com.alibaba.sdk.exception;

import com.alibaba.sdk.enums.ErrorCodeEnums;
import com.alibaba.sdk.model.OperationResult;
import com.alibaba.sdk.util.HttpRequestUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindException;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import javax.servlet.http.HttpServletRequest;
import java.util.stream.Collectors;

/**
 * 公共异常处理
 *
 * @ author  Shawn(Shawn_0217@163.com)
 * @ date    2021/5/11 11:03
 * @ company Alibaba
 */
@Slf4j
@Order(1)
@RestControllerAdvice
@ControllerAdvice(annotations = {Controller.class, RestController.class})
public class GlobalControllerExceptionHandler {

    /**
     * 兜底异常处理
     *
     * @param request
     * @param e
     * @return
     */
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public OperationResult handleException(HttpServletRequest request, Exception e) {
        String reqUri = HttpRequestUtil.delPathVariable(request);
        log.info("reqUri = {}", reqUri);
        log.warn("Exception:", e);
        String errorMsg = StringUtils.isNotBlank(e.getMessage()) ? e.getMessage() : ErrorCodeEnums.INTERNAL_SERVER_ERROR.getErrorMsg();
        return new OperationResult(ErrorCodeEnums.INTERNAL_SERVER_ERROR.getErrorCode(), errorMsg);
    }

    @ExceptionHandler(BusinessException.class)
    public OperationResult handleErrorCodeException(HttpServletRequest request, BusinessException e) {
        String reqUri = HttpRequestUtil.delPathVariable(request);
        log.info("reqUri = {}", reqUri);
        log.warn("BusinessException:", e.getErrorMessage());
        return new OperationResult(e.getErrorCode(), e.getErrorMessage());
    }

    @ExceptionHandler(StreamDownloadException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public void handleHttpStreamDownloadException(HttpServletRequest request, StreamDownloadException e) {
        String reqUri = HttpRequestUtil.delPathVariable(request);
        log.info("reqUri = {}", reqUri);
        log.warn("BusinessException:", e.getMessage());
    }

    /**
     * spring 参数绑定异常处理
     *
     * @param request
     * @param e
     * @return
     */
    @ExceptionHandler(BindException.class)
    public OperationResult handle(HttpServletRequest request, BindException e) {
        String reqUri = HttpRequestUtil.delPathVariable(request);
        log.info("reqUri = {}", reqUri);
        String message = String.join(", ", e.getBindingResult().getFieldErrors().stream().map(item -> item.getDefaultMessage()).collect(Collectors.toList()));
        log.warn("BindException:", message);
        return new OperationResult(ErrorCodeEnums.PARAMETER_ERROR.getErrorCode(), message);
    }

    /**
     * 枚举转换异常处理
     *
     * @param request
     * @param e
     * @return
     */
    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    @ResponseBody
    public OperationResult handleEnumConvertException(HttpServletRequest request, MethodArgumentTypeMismatchException e) {
        String reqUri = HttpRequestUtil.delPathVariable(request);
        log.info("reqUri = {}", reqUri);
        log.warn("MethodArgumentTypeMismatchException:", e.getMessage());
        return new OperationResult(ErrorCodeEnums.ENUM_CONVERT_ERROR.getErrorCode(), ErrorCodeEnums.ENUM_CONVERT_ERROR.getErrorMsg());
    }

}
